package com.shuosen.gmall.list.service;

import com.alibaba.dubbo.config.annotation.Service;
import com.shuosen.gmall.bean.SkuLsInfo;
import com.shuosen.gmall.bean.SkuLsParams;
import com.shuosen.gmall.bean.SkuLsResult;
import com.shuosen.gmall.config.RedisUtil;
import com.shuosen.gmall.service.ListService;
import io.searchbox.client.JestClient;
import io.searchbox.core.Index;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import io.searchbox.core.Update;
import io.searchbox.core.search.aggregation.Aggregation;
import io.searchbox.core.search.aggregation.MetricAggregation;
import io.searchbox.core.search.aggregation.TermsAggregation;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.Jedis;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class ListServiceImpl  implements ListService {

    public static final String ES_INDEX="gmall";

    public static final String ES_TYPE="SkuInfo";

    @Autowired
    private RedisUtil redisUtil  ;

    @Autowired
    JestClient  jestClient ;
    @Override
    public void saveSkuLsInfo(SkuLsInfo skuLsInfo) {
        //保存操作  
        //put/index/type/id{data}
        //put/gamll/skuInfo/1/{}
        Index index = new Index.Builder(skuLsInfo).index(ES_INDEX).type(ES_TYPE).id(skuLsInfo.getId()).build();

        try {
            //执行操作
            jestClient.execute(index);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public SkuLsResult search(SkuLsParams skuLsParams) {
        /***
         * 先定义一个dsl语句
         * 将dsl语句放入查询器
         * 执行查询
         * 将执行的结果集返回
         *
         */
        String query = makeQueryStringForSearch(skuLsParams);
        Search search = new Search.Builder(query).addIndex(ES_INDEX).addType(ES_TYPE).build();
        SearchResult searchResult = null ;
        try {
             searchResult =  jestClient.execute(search);
        } catch (IOException e) {
            e.printStackTrace();
        }
        SkuLsResult result =  makeResultForSearch(skuLsParams,searchResult);
        return result;
    }

    @Override
    public void incrHotScore(String skuId) {
        Jedis jedis = redisUtil.getJedis();
        //jedis如何记录用户访问的数据
        //知道五种数据类型
        Double hotScore = jedis.zincrby("hotScore", 1, "skuId:" + skuId);

        //需要跟一个计数规则进行存值
        if(hotScore%10 ==0 ){
            //更新es这个的hotscore Math.round(11.5) 12  Math.round(-11.5)  -11
            updateHotScore(skuId,Math.round(hotScore));
        }
    }

    private void updateHotScore(String skuId, long round) {
        //更新es

        String query = "\t{\n" +
                "\t   \"doc\":{\n" +
                "\t      \"hotScore\":"+skuId+"\n" +
                "\t   }\n" +
                "\t}" ;
        Update update  = new Update.Builder(query).index(ES_INDEX).type(ES_TYPE).id(skuId).build();

        try {
            jestClient.execute(update);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /***
     * 制作返回结果集
     * @param skuLsParams
     * @param searchResult
     * @return
     */
    private SkuLsResult makeResultForSearch(SkuLsParams skuLsParams, SearchResult searchResult) {
        //返回结果集的list
         SkuLsResult result = new SkuLsResult();
        //  private List<SkuLsInfo> skuLsInfoList;
        //    private long totalPages;
        //    private List<String> attrValueIdList;
        ArrayList<SkuLsInfo> skuLsInfoList = new ArrayList<>();
        List<SearchResult.Hit<SkuLsInfo, Void>> hits = searchResult.getHits(SkuLsInfo.class);
        if(hits!=null && hits.size()>0){
            for (SearchResult.Hit<SkuLsInfo, Void> hit : hits) {
                SkuLsInfo skuLsInfo = hit.source;
                //取出skuName的高亮
                if(hit.highlight!=null && hit.highlight.size()>0){
                    Map<String, List<String>> map = hit.highlight;
                    //<span style=color:red>小米</span><span style=color:red>8SE</span>
                    String skuNameHi = map.get("skuName").get(0);
                    //将其SkuNameHi 放入skuLsInfo替换到skuName
                    skuLsInfo.setSkuName(skuNameHi);
                }
                //将其加入到集合中
                skuLsInfoList.add(skuLsInfo);


            }
        }
        result.setSkuLsInfoList(skuLsInfoList);

        //    private long total;
        result.setTotal(searchResult.getTotal());


        //    private long totalPages;
        //公式 如何计算总页数
//         long totalPages = searchResult.getTotal() % skuLsParams.getPageSize()==0?searchResult.getTotal():searchResult.getTotal()+1;
        long totalPages = (searchResult.getTotal()+skuLsParams.getPageSize()-1)/skuLsParams.getPageSize();
        result.setTotalPages(totalPages);
        //声明一个集合来存储 平台属性值id
        ArrayList<String> valueIdList = new ArrayList<>();
        //在聚合中获取平台属性值的id
        MetricAggregation aggregations = searchResult.getAggregations();
        Aggregation groupby_attr = aggregations.getTermsAggregation("groupby_attr");
        List<TermsAggregation.Entry> buckets = ((TermsAggregation) groupby_attr).getBuckets();
        if(buckets!=null && buckets.size() > 0){
            for (TermsAggregation.Entry bucket : buckets) {
                String valueId = bucket.getKey();
                valueIdList.add(valueId);
            }
        }
        //获取属性值ID的集合
        result.setAttrValueIdList(valueIdList);
        return result;
    }

    private String makeQueryStringForSearch(SkuLsParams skuLsParams) {
        //动态生成dsl语句
       //创建一个查询器
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //"query"
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //判断输入的skuName是否为空
        if(skuLsParams.getKeyword()!=null && skuLsParams.getKeyword().length() >0){
            MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("skuName", skuLsParams.getKeyword());
            //bool must
            boolQueryBuilder.must(matchQueryBuilder);

            //设置高亮
            HighlightBuilder highlighter = searchSourceBuilder.highlighter();
            //设置高亮字段
            highlighter.field("skuName");
            highlighter.preTags("<span style=color:red>");
            highlighter.postTags("</span>");

            //将设置后的对象，放入查询器，使其生效
            searchSourceBuilder.highlight(highlighter);
        }
        //操作三级分类id
        if(skuLsParams.getCatalog3Id()!=null && skuLsParams.getCatalog3Id().length()>0){
            
            TermQueryBuilder termQueryBuilder = new TermQueryBuilder("catalog3Id",skuLsParams.getCatalog3Id());

            //bool - filter -- term 
            boolQueryBuilder.filter(termQueryBuilder);
            
            
        }
        
        //设置平台属性值id  
        if(skuLsParams.getValueId()!=null && skuLsParams.getValueId().length>0){
            //循环遍历 
            for (String valueId : skuLsParams.getValueId()) {
                TermQueryBuilder termQueryBuilder = new TermQueryBuilder("skuAttrValueList.valueId",valueId);
                  boolQueryBuilder.filter(termQueryBuilder);
            }
        }
        //分页   分页公式
        //from  = (pageNumber -1 )*pageSize
        // 10 条数据 一页显示3条 一共4页
        int from = (skuLsParams.getPageNo()-1)* skuLsParams.getPageSize();
        searchSourceBuilder.from(from);
        searchSourceBuilder.size(skuLsParams.getPageSize());
        //排序
        searchSourceBuilder.sort("hotScore", SortOrder.DESC);

        //设置聚合agg规则
        TermsBuilder groupby_attr = AggregationBuilders.terms("groupby_attr").field("skuAttrValueList.valueId");
        //将聚合对象放入查询器
        searchSourceBuilder.aggregation(groupby_attr);
        //"query"
        searchSourceBuilder.query(boolQueryBuilder);
        String query = searchSourceBuilder.toString();
        System.out.println("query:="+query);
        return query;
    }
}
